﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using FreeRedis;
using GoodsService.Application.Contract.DTO.Input;
using GoodsService.Application.Contract.DTO.Output;
using GoodsService.Application.Contract.IAppService;
using GoodsService.Domain.Aggregate.Collection;
using GoodsService.Domain.Repository;
using LeoGemini.Service.Infrastructure.Extension;
using LeoGemini.Service.Infrastructure.Handler.Exception;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Services;

namespace GoodsService.Application.AppService
{
    public class CollectionAppService : ApplicationService, ICollectionAppService
    {
        private readonly ICollectionRepository _collectionRepository;
        private readonly RedisClient _cache;

        public CollectionAppService(
            ICollectionRepository collectionRepository,
            RedisClient cache)
        {
            _collectionRepository = collectionRepository;
            _cache = cache;
        }
        
        /// <summary>
        /// 分页获取系列id
        /// </summary>
        public async Task<PaginationOutputDto<string>> GetCollectionsByPaginationAsync(int p, int n)
        {
            if (p < 0)
                throw new BadRequestException(ErrorMessage.PAGINATION_PEGE_ERROR);
            
            var collectionIds = new List<string>(
                _cache.ZRange("collectionIds", p * n, p * n + n - 1)
            );
            
            if (collectionIds.Count == 0)
            {
                var collections = await _collectionRepository
                    .OrderBy(collection => collection.CreationTime)
                    .Skip(p * n).Take(n).ToListAsync();
                // 缓存结果
                foreach (var data in collections)
                {
                    _cache.ZAdd("collectionIds",
                        data.CreationTime.ToUnixTimeTicks(),
                        data.Id);
                    collectionIds.Add(data.Id);
                }
            }

            var totalNum = await _collectionRepository.CountAsync();

            return new PaginationOutputDto<string>
            {
                Num = totalNum,
                Ids = collectionIds
            };
        }

        /// <summary>
        /// 根据系列id获取系列信息
        /// </summary>
        public async Task<CreateCollectionReturnDto> GetCollectionByIdAsync(string collectionId)
        {
            var collection = await _cache.CacheOrGetAsync($"collections:collection:{collectionId}",
                async () => await _collectionRepository.FindAsync(collectionId));

            if (collection == null)
                throw new NotFoundException(ErrorMessage.COLLECTION_NOT_FOUND);

            return ObjectMapper.Map<Collection, CreateCollectionReturnDto>(collection);
        }

        /// <summary>
        /// 添加系列
        /// </summary>
        public async Task<CreateCollectionReturnDto> CreateCollectionAsync(CreateCollectionInputDto dto)
        {
            // 新建系列
            var collection = new Collection(new Random().Next(6, Extensions.MixinType.Upper), dto.Title, dto.Intro);
            
            // 持久化
            collection = await _collectionRepository.InsertAsync(collection);
            
            // 添加id到分页缓存
            _cache.ZAdd("collectionIds",
                collection.CreationTime.ToUnixTimeTicks(),
                collection.Id);

            return ObjectMapper.Map<Collection, CreateCollectionReturnDto>(collection);
        }

        /// <summary>
        /// 删除系列
        /// </summary>
        public async Task DeleteCollectionByIdAsync(string collectionId)
        {
            // 数据库获取
            var collection = await _collectionRepository.FindAsync(collectionId);
            
            // 系列不存在
            if (collection == null)
                throw new NotFoundException(ErrorMessage.COLLECTION_NOT_FOUND);

            await _cache.RemoveAndPersistAsync(
                async () =>
                {
                    await _collectionRepository.DeleteAsync(collection);
                }, $"collections:collection:{collectionId}");
            _cache.ZRem("collectionIds", collectionId);
        }

        /// <summary>
        /// 修改系列
        /// </summary>
        public async Task<CreateCollectionReturnDto> EditCollectionByIdAsync(string collectionId, EditCollectionInputDto dto)
        {
            var cacheKey = $"collections:collection:{collectionId}";
            // 获取聚合根
            var collection = await _cache.CacheOrGetAsync(cacheKey,
                async () => await _collectionRepository.FindAsync(collectionId));
            
            // 系列不存在
            if (collection == null)
                throw new NotFoundException(ErrorMessage.COLLECTION_NOT_FOUND);
            
            // 变更属性
            collection.ChangeTitle(dto.Title);
            collection.ChangeIntro(dto.Intro);

            // 持久化并删除缓存
            await _cache.RemoveAndPersistAsync(
                async () =>
                {
                    await _collectionRepository.UpdateAsync(collection);
                }, cacheKey);

            return ObjectMapper.Map<Collection, CreateCollectionReturnDto>(collection);
        }
    }
}